//! gRPC客户端实现
//! 
//! 实现与沙箱管理系统的gRPC通信

use crate::api::client::*;
use crate::{Result, Error};
use crate::types::{SandboxId as InternalSandboxId, SandboxState};
use async_trait::async_trait;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{info, warn, error, debug};

/// gRPC沙箱管理器客户端实现
pub struct GrpcSandboxManagerClient {
    /// 连接池配置
    connection_config: ConnectionPoolConfig,
    /// 沙箱管理器引用
    sandbox_manager: Arc<crate::sandbox_manager::SandboxManager>,
    /// 池化管理器引用
    pool_manager: Arc<RwLock<Option<Arc<crate::pool::LayeredPoolManager>>>>,
}

impl GrpcSandboxManagerClient {
    /// 创建新的gRPC客户端
    pub fn new(
        connection_config: ConnectionPoolConfig,
        sandbox_manager: Arc<crate::sandbox_manager::SandboxManager>,
    ) -> Self {
        Self {
            connection_config,
            sandbox_manager,
            pool_manager: Arc::new(RwLock::new(None)),
        }
    }
    
    /// 设置池化管理器
    pub async fn set_pool_manager(&self, pool_manager: Arc<crate::pool::LayeredPoolManager>) {
        let mut guard = self.pool_manager.write().await;
        *guard = Some(pool_manager);
    }
    
    /// 转换执行结果
    fn convert_execution_result(&self, internal: crate::types::ExecutionResult) -> ExecutionResult {
        ExecutionResult {
            success: internal.success,
            stdout: internal.stdout,
            stderr: internal.stderr,
            exit_code: internal.exit_code,
            execution_time_ms: internal.execution_time_ms,
            memory_usage_mb: internal.memory_usage_mb,
        }
    }
}

#[async_trait]
impl SandboxManagerClient for GrpcSandboxManagerClient {
    /// 请求分配沙箱
    async fn allocate_sandbox(&self, request: SandboxRequest) -> Result<SandboxInfo> {
        info!("分配沙箱请求 - 语言: {:?}, 优先级: {:?}", request.language, request.priority);
        
        // 检查池化管理器
        let pool_manager = self.pool_manager.read().await;
        if let Some(ref pool_mgr) = *pool_manager {
            // 从池中获取沙箱
            match pool_mgr.acquire_sandbox(&request.language).await {
                Ok(Some(sandbox)) => {
                    info!("成功从池中分配沙箱: {}", sandbox.metadata.id);
                    
                    return Ok(SandboxInfo {
                        sandbox_id: sandbox.metadata.id,
                        language: request.language,
                        state: sandbox.metadata.state.clone(),
                        allocated_at: std::time::SystemTime::now(),
                        resources: request.resources,
                    });
                }
                Ok(None) => {
                    warn!("池中无可用沙箱，需要创建新沙箱");
                }
                Err(e) => {
                    error!("从池中获取沙箱失败: {}", e);
                    return Err(e);
                }
            }
        }
        
        // 如果池中没有可用沙箱，创建新的
        let spec = crate::types::SandboxSpec {
            language: request.language.clone(),
            memory_mb: request.resources.memory_mb as u64,
            cpu_cores: request.resources.cpu_cores,
            disk_mb: request.resources.disk_mb as u64,
            timeout_secs: request.timeout.as_secs(),
            network_enabled: request.resources.network_enabled,
            ..Default::default()
        };
        
        let sandbox_id = self.sandbox_manager.create_sandbox(spec).await?;
        
        // 启动沙箱
        self.sandbox_manager.start_sandbox(sandbox_id).await?;
        
        Ok(SandboxInfo {
            sandbox_id,
            language: request.language,
            state: SandboxState::Running,
            allocated_at: std::time::SystemTime::now(),
            resources: request.resources,
        })
    }
    
    /// 执行代码
    async fn execute_code(&self, sandbox_id: String, code: CodePayload) -> Result<ExecutionResult> {
        debug!("执行代码请求 - 沙箱: {}, 语言: {:?}", sandbox_id, code.language);
        
        // 解析沙箱ID
        let sandbox_id = sandbox_id.parse::<InternalSandboxId>()
            .map_err(|_| Error::validation("Invalid sandbox ID"))?;
        
        // 构建执行请求
        let exec_request = crate::types::ExecutionRequest {
            sandbox_id,
            source_code: code.source_code,
            language: code.language,
            entry_point: "main".to_string(),
            dependencies: vec![],
            env_vars: code.env_vars,
            stdin: "".to_string(),
            timeout_ms: Some(30000), // 默认30秒超时
        };
        
        // 执行代码
        let result = self.sandbox_manager.execute_code(sandbox_id, exec_request).await?;
        
        Ok(self.convert_execution_result(result))
    }
    
    /// 释放沙箱
    async fn release_sandbox(&self, sandbox_id: String) -> Result<()> {
        debug!("释放沙箱请求: {}", sandbox_id);
        
        // 解析沙箱ID
        let sandbox_id = sandbox_id.parse::<InternalSandboxId>()
            .map_err(|_| Error::validation("Invalid sandbox ID"))?;
        
        // 检查池化管理器
        let pool_manager = self.pool_manager.read().await;
        if let Some(ref pool_mgr) = *pool_manager {
            // 尝试将沙箱返回池中
            if let Some(sandboxes) = self.sandbox_manager.get_sandboxes().await {
                if let Some(sandbox) = sandboxes.get(&sandbox_id) {
                    // TODO: 暂时跳过复杂的沙箱释放逻辑，避免clone
                    warn!("暂时跳过沙箱释放到池中的逻辑");
                    // 直接销毁沙箱而不是释放回池
                }
            }
        }
        
        // 如果无法返回池，直接销毁
        self.sandbox_manager.destroy_sandbox(sandbox_id).await
    }
    
    /// 获取沙箱状态
    async fn get_sandbox_status(&self, sandbox_id: String) -> Result<SandboxStatus> {
        debug!("获取沙箱状态请求: {}", sandbox_id);
        
        // 解析沙箱ID
        let sandbox_id = sandbox_id.parse::<InternalSandboxId>()
            .map_err(|_| Error::validation("Invalid sandbox ID"))?;
        
        // 获取沙箱信息
        if let Some(sandboxes) = self.sandbox_manager.get_sandboxes().await {
            if let Some(metadata) = sandboxes.get(&sandbox_id) {
                let health = if self.sandbox_manager.is_sandbox_healthy(sandbox_id).await {
                    HealthStatus::Healthy
                } else {
                    HealthStatus::Unhealthy("Health check failed".to_string())
                };
                
                return Ok(SandboxStatus {
                    sandbox_id,
                    state: metadata.state.clone(),
                    uptime: metadata.uptime(),
                    usage_count: metadata.usage_count as usize,
                    last_used_at: metadata.last_used,
                    health,
                });
            }
        }
        
        Err(Error::sandbox_not_found(sandbox_id.to_string()))
    }
}

/// REST API沙箱管理器客户端实现
pub struct RestSandboxManagerClient {
    /// 基础URL
    base_url: String,
    /// HTTP客户端
    client: reqwest::Client,
}

impl RestSandboxManagerClient {
    /// 创建新的REST客户端
    pub fn new(base_url: String) -> Result<Self> {
        let client = reqwest::Client::builder()
            .timeout(std::time::Duration::from_secs(30))
            .build()
            .map_err(|e| Error::network(e.to_string()))?;
        
        Ok(Self {
            base_url,
            client,
        })
    }
}

#[async_trait]
impl SandboxManagerClient for RestSandboxManagerClient {
    async fn allocate_sandbox(&self, request: SandboxRequest) -> Result<SandboxInfo> {
        let url = format!("{}/api/v1/sandboxes", self.base_url);
        
        let response = self.client
            .post(&url)
            .json(&request)
            .send()
            .await
            .map_err(|e| Error::network(e.to_string()))?;
        
        if response.status().is_success() {
            response.json::<SandboxInfo>()
                .await
                .map_err(|e| Error::network(e.to_string()))
        } else {
            Err(Error::api(format!("Failed to allocate sandbox: {}", response.status())))
        }
    }
    
    async fn execute_code(&self, sandbox_id: String, code: CodePayload) -> Result<ExecutionResult> {
        let url = format!("{}/api/v1/sandboxes/{}/execute", self.base_url, sandbox_id);
        
        let response = self.client
            .post(&url)
            .json(&code)
            .send()
            .await
            .map_err(|e| Error::network(e.to_string()))?;
        
        if response.status().is_success() {
            response.json::<ExecutionResult>()
                .await
                .map_err(|e| Error::network(e.to_string()))
        } else {
            Err(Error::api(format!("Failed to execute code: {}", response.status())))
        }
    }
    
    async fn release_sandbox(&self, sandbox_id: String) -> Result<()> {
        let url = format!("{}/api/v1/sandboxes/{}", self.base_url, sandbox_id);
        
        let response = self.client
            .delete(&url)
            .send()
            .await
            .map_err(|e| Error::network(e.to_string()))?;
        
        if response.status().is_success() {
            Ok(())
        } else {
            Err(Error::api(format!("Failed to release sandbox: {}", response.status())))
        }
    }
    
    async fn get_sandbox_status(&self, sandbox_id: String) -> Result<SandboxStatus> {
        let url = format!("{}/api/v1/sandboxes/{}/status", self.base_url, sandbox_id);
        
        let response = self.client
            .get(&url)
            .send()
            .await
            .map_err(|e| Error::network(e.to_string()))?;
        
        if response.status().is_success() {
            response.json::<SandboxStatus>()
                .await
                .map_err(|e| Error::network(e.to_string()))
        } else {
            Err(Error::api(format!("Failed to get sandbox status: {}", response.status())))
        }
    }
}